﻿using Microsoft.WindowsAzure;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Web;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Umbraco.Core.IO;
using System.Web.Configuration;


namespace Umbraco.AzureStorage
{
    public class BlobFileSystem : IFileSystem
    {
        string containerName;
        CloudStorageAccount account; 
        CloudBlobClient cloudBlobClient; 

        public BlobFileSystem(string virtualRoot)
        {
            containerName = WebConfigurationManager.AppSettings["StorageContainer"].ToString();
            string storageAccountName = WebConfigurationManager.AppSettings["StorageAccountName"].ToString();
            string storageAccessKey = WebConfigurationManager.AppSettings["StorageAccessKey"].ToString();
    
            account = new CloudStorageAccount(new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(storageAccountName, storageAccessKey), false);
            cloudBlobClient = account.CreateCloudBlobClient();
        }

        public void AddFile(string path, System.IO.Stream stream, bool overrideIfExists)
        {
            path = path.ToLower();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            cloudBlobContainer.CreateIfNotExists();

            var blob = cloudBlobContainer.GetBlockBlobReference(path);
            stream.Position = 0;
            blob.UploadFromStream(stream);
        }


        public void AddFile(string path, System.IO.Stream stream)
        {
            path = path.ToLower();
            AddFile(path, stream, true);
        }

        public void DeleteDirectory(string path, bool recursive)
        {
            throw new Exception("Not implemented");
            //string directory = Path.GetDirectoryName(path);
            //var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            //cloudBlobContainer.Delete();
        }

        public void DeleteDirectory(string path)
        {
            DeleteDirectory(path, true);
        }

        public void DeleteFile(string path)
        {
            path = path.ToLower();
            string directory = Path.GetDirectoryName(path);
            string fileName = Path.GetFileName(path);

            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(fileName);
            blob.DeleteIfExists();

        }

        public bool DirectoryExists(string path)
        {
            throw new Exception("Not implemented");
            string directory = Path.GetDirectoryName(path);
            string fileName = Path.GetFileName(path);

            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName + directory);
            return cloudBlobClient != null;
        }

        public bool FileExists(string path)
        {
            path = path.ToLower();
            string directory = Path.GetDirectoryName(path);
            string fileName = Path.GetFileName(path);

            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(path);

            return blob != null;
        }

        public DateTimeOffset GetCreated(string path)
        {
            path = path.ToLower();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(path);

            return blob.Properties.LastModified ?? DateTime.MinValue;

        }

        public IEnumerable<string> GetDirectories(string path)
        {
            throw new Exception("Not implemented");
        }

        public IEnumerable<string> GetFiles(string path, string filter)
        {
            path = path.ToLower();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            return cloudBlobContainer.ListBlobs().OfType<string>();
        }

        public IEnumerable<string> GetFiles(string path)
        {
            path = path.ToLower();
            var blobDirectory = cloudBlobClient.GetContainerReference(containerName);
            return blobDirectory.ListBlobs().OfType<string>();
        }

        public string GetFullPath(string path)
        {
            path = path.ToLower();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(path);

            return blob.Uri.ToString();
        }

        public DateTimeOffset GetLastModified(string path)
        {
            path = path.ToLower();
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(path);

            return blob.Properties.LastModified ?? DateTime.MinValue;
        }

        public string GetRelativePath(string fullPathOrUrl)
        {
            var relativePath = "";
            if (fullPathOrUrl.Contains(containerName))
            {
                int containerIdx = fullPathOrUrl.IndexOf(containerName) + containerName.Length + 1;
                relativePath = fullPathOrUrl.Substring(containerIdx, fullPathOrUrl.Length - containerIdx);
            }
            else
            {
                return fullPathOrUrl.ToLower();
            }
            return relativePath.ToLower();
        }

        public string GetUrl(string path)
        {
            path = path.ToLower();
            if (path.StartsWith("/"))
                return path;
            else
            {
                try
                {
                    var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);

                    var blob = cloudBlobContainer.GetBlockBlobReference(path);
                    return blob.Uri.ToString();
                }
                catch (Exception ex)
                {
                    return "empty";
                }
            }
        }

        public System.IO.Stream OpenFile(string path)
        {
            path = path.ToLower();
         
            var cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName);
            var blob = cloudBlobContainer.GetBlockBlobReference(path);
            Stream s = new MemoryStream();
            blob.DownloadToStream(s);
            s.Position = 0;
            return s;
        }
    }
}
